package version4.Client.CircuitBreaker;

import lombok.Getter;

import java.util.concurrent.atomic.AtomicInteger;


public class CircuitBreaker {
    private CircuitBreakerState state = CircuitBreakerState.CLOSED;
    // 记录在半开状态的成功率
    private AtomicInteger failureCount = new AtomicInteger(0);
    private AtomicInteger successCount = new AtomicInteger(0);
    private AtomicInteger requestCount = new AtomicInteger(0);

    // 失败阈值,超过该阈值比例则将状态置为OPEN
    private final double failureRate;
    // 成功阈值,超过该阈值比例则将状态置为CLOSED
    private final double halfOpenSuccessRate;
    // 恢复时间，Open状态持续该时间后，将状态置为HALF_OPEN
    private final long openTime;
    private long lastFailureTime = 0;

    public CircuitBreaker(double failureRate, double halfOpenSuccessRate, long openTime) {
        this.failureRate = failureRate;
        this.halfOpenSuccessRate = halfOpenSuccessRate;
        this.openTime = openTime;
    }

    // 每次调用服务前，调用此方法判断是否允许请求
    public synchronized boolean allowRequest() {
        switch (state) {
            case OPEN:
                long currentTime = System.currentTimeMillis();
                if (currentTime - lastFailureTime > openTime) {
                    state = CircuitBreakerState.HALF_OPEN;
                    return true;
                } else {
                    System.out.println("熔断器处于开放状态，拒绝请求");
                    return false;
                }
            case HALF_OPEN:
                // 半开状态下，允许请求
            case CLOSED:
            default:
                requestCount.incrementAndGet();
                return true;
        }
    }

    // 外部调用服务成功，调用此方法
    public synchronized void recordSuccess() {
        if(state == CircuitBreakerState.HALF_OPEN || state == CircuitBreakerState.CLOSED){
            successCount.incrementAndGet();
            System.out.println("熔断器状态：" + state + ", 成功次数：" + successCount.get());
            if (state == CircuitBreakerState.HALF_OPEN) {
                if (successCount.get() >= halfOpenSuccessRate * requestCount.get()) {
                    state = CircuitBreakerState.CLOSED;
                    resetCount();
                }
            }
        }
    }

    // 外部调用服务失败，调用此方法
    public synchronized void recordFailure() {
        if(state == CircuitBreakerState.HALF_OPEN || state == CircuitBreakerState.CLOSED){
            failureCount.incrementAndGet();
            System.out.println("熔断器状态：" + state + ", 失败次数：" + failureCount.get());
            // 防止一次失败，将状态置为OPEN
            if (failureCount.get() >= Math.min(3,failureRate * requestCount.get())) {
                // 在半开状态或者关闭状态下，失败次数超过阈值，将状态置为OPEN
                state = CircuitBreakerState.OPEN;
                resetCount();
                lastFailureTime = System.currentTimeMillis();
            }
        }
    }

    private void resetCount() {
        failureCount.set(0);
        successCount.set(0);
        requestCount.set(0);
    }

    public CircuitBreakerState getState() {
        return state;
    }
}


enum CircuitBreakerState {
    CLOSED,
    OPEN,
    HALF_OPEN
}
